package com.szwistar.common.comm.minahttpserver;

import org.apache.log4j.PropertyConfigurator;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;

public class HttpServer {
	protected static final Logger LOG = LoggerFactory.getLogger(HttpServer.class);

	/** Default HTTP port */
	private static final int DEFAULT_PORT = 8080;
	private NioSocketAcceptor acceptor;
	private boolean isRunning;

	private String encoding;
	// HTTP 请求拦截处理器
	private List<HttpRequestInterceptor> interceptors = new ArrayList<HttpRequestInterceptor>();

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
		HttpRequestDecoder.defaultEncoding = encoding;
		HttpResponseEncoder.defaultEncoding = encoding;
	}

	public void addInterceptor(HttpRequestInterceptor interceptor) {
		interceptors.add(interceptor);
	}

	/**
	 * 启动HTTP服务端监听HTTP请求
	 * @param port要监听的端口号
	 * @throws IOException
	 */
	public void run(int port) throws Exception {
		synchronized (this) {
			if (isRunning) {
				System.out.println("Server is already running.");
				return;
			}

			acceptor = new NioSocketAcceptor();
			acceptor.getFilterChain().addLast("protocolFilter", new ProtocolCodecFilter(new HttpServerProtocolCodecFactory()));
			// acceptor.getFilterChain().addLast("logger", new LoggingFilter());

			ServerHandler handler = new ServerHandler(interceptors);
			acceptor.setHandler(handler);
			acceptor.bind(new InetSocketAddress(port));
			isRunning = true;
			System.out.println("Server now listening on port " + port);
		}
	}

	/**
	 * 使用默认端口8080
	 */
	public void run() throws Exception {
		run(DEFAULT_PORT);
	}

	/**
	 * 停止监听HTTP服务
	 */
	public void stop() {
		synchronized (this) {
			if (!isRunning) { return; }
			isRunning = false;

			try {
				acceptor.unbind();
				acceptor.dispose();
				LOG.info("Server is stoped.");
			} catch (Exception e) {
				LOG.error("", e);
			}
		}
	}

	public static void main(String[] args) throws Exception
	{
		// 加载日志配置文件（放在jar同级的conf目录下）
		PropertyConfigurator.configure("log4j.properties");

		HttpServer server = new HttpServer();
		server.setEncoding("UTF-8");

		server.addInterceptor(new HttpRequestInterceptor() {
			@Override
			public boolean handle(HttpRequest request, HttpResponse response) {
				String level = request.getParameter("level");
				System.out.println(request.getParameter("level"));
				System.out.println(request.getContext());

				response.setContentType("text/plain; charset=utf-8");
				response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
				response.appendBody("你好\n");
				response.appendBody(level);
				return false;
			}
		});
		server.run(8080);

		Thread.sleep(10000);
		// server.stop();
	}
}

class HttpServerProtocolCodecFactory extends DemuxingProtocolCodecFactory {
	public HttpServerProtocolCodecFactory() {
		super.addMessageDecoder(HttpRequestDecoder.class);
		super.addMessageEncoder(HttpResponse.class, HttpResponseEncoder.class);
	}
}

class ServerHandler implements IoHandler {
	// HTTP 请求拦截处理器
	private List<HttpRequestInterceptor> interceptors = new ArrayList<HttpRequestInterceptor>();

	public ServerHandler(List<HttpRequestInterceptor> interceptors) {
		super();
		this.interceptors = interceptors;
	}

	@Override
	public void sessionCreated(IoSession session) {
	}

	@Override
	public void sessionOpened(IoSession session) {
		// set idle time to 60 seconds
		session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 60);
	}

	@Override
	public void messageReceived(IoSession session, Object message) {
		// Check that we can service the request context
		HttpRequest request = (HttpRequest) message;
		HttpResponse response = new HttpResponse();

		try {
			// 逐个调用各个 HTTP 请求拦截处理器对请求进行处理
			for(HttpRequestInterceptor interceptor: interceptors) {
				if(!interceptor.handle(request, response)) { break; }
			}
		} catch (Exception e) {
			response.setResponseCode(500);
			response.appendBody(e.getMessage());
			response.setContentType("text/plain; charset=utf-8");
		}

		// 发送 HTTP 响应
		session.write(response).addListener(IoFutureListener.CLOSE);
	}

	@Override
	public void messageSent(IoSession session, Object message) {
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) {
		session.close(false);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) {
		session.close(false);
	}

	@Override
	public void sessionClosed(IoSession session) {
	}
}
